package johnkkk.com.obj;

import android.opengl.GLES32;
import android.opengl.GLUtils;
import android.os.Build;
import android.support.annotation.RequiresApi;

import com.graphics.element.AbsSceneNode;
import com.system.GLApplication;
import com.system.GLLog;
import com.system.Shader;
import com.tools.GLBufferTools;
import com.tools.SizeOf;
import com.tools.TextureTools;

import java.nio.FloatBuffer;

/**
 * @Author: clm
 * @Date: 2018-10-30
 */

public class FBOObj extends AbsSceneNode {
    public int mFBO[];
    public int mColorBuffer[];
    private int mScreenVAO[];
    private Shader mScreenShader;
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public FBOObj(String name) {
        super(name);
        mFBO = new int[1];
        GLES32.glGenFramebuffers(1, mFBO, 0);
        GLES32.glBindFramebuffer(GLES32.GL_FRAMEBUFFER, mFBO[0]);
        //设置fbo颜色缓存
        mColorBuffer = new int[1];
        GLES32.glGenTextures(1, mColorBuffer, 0);
        GLES32.glBindTexture(GLES32.GL_TEXTURE_2D, mColorBuffer[0]);
        //int target, int level, int internalformat, int width, int height, int border, int format, int type, Buffer pixels
        GLES32.glTexImage2D(GLES32.GL_TEXTURE_2D, 0, GLES32.GL_RGB, GLApplication.sWidth, GLApplication.sHeight, GLES32.GL_FALSE, GLES32.GL_RGB, GLES32.GL_UNSIGNED_BYTE, null);
        GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_MAG_FILTER, GLES32.GL_LINEAR);
        GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_MIN_FILTER, GLES32.GL_LINEAR);
        GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_WRAP_S, GLES32.GL_CLAMP_TO_EDGE);
        GLES32.glTexParameteri(GLES32.GL_TEXTURE_2D, GLES32.GL_TEXTURE_WRAP_T, GLES32.GL_CLAMP_TO_EDGE);
        GLES32.glFramebufferTexture2D(GLES32.GL_FRAMEBUFFER, GLES32.GL_COLOR_ATTACHMENT0, GLES32.GL_TEXTURE_2D, mColorBuffer[0], 0);
        GLES32.glBindTexture(GLES32.GL_TEXTURE_2D, 0);
        //设置fbo深度缓存和模板缓存附件
        int depthAndstencilBuffer[] = new int[1];
        GLES32.glGenRenderbuffers(1, depthAndstencilBuffer, 0);
        GLES32.glBindRenderbuffer(GLES32.GL_RENDERBUFFER, depthAndstencilBuffer[0]);
        GLES32.glRenderbufferStorage(GLES32.GL_RENDERBUFFER, GLES32.GL_DEPTH24_STENCIL8, GLApplication.sWidth, GLApplication.sHeight);
        GLES32.glFramebufferRenderbuffer(GLES32.GL_FRAMEBUFFER, GLES32.GL_DEPTH_STENCIL_ATTACHMENT, GLES32.GL_RENDERBUFFER, depthAndstencilBuffer[0]);
        GLES32.glBindRenderbuffer(GLES32.GL_RENDERBUFFER, 0);
        //检查fbo状态
        if(GLES32.glCheckFramebufferStatus(GLES32.GL_FRAMEBUFFER) != GLES32.GL_FRAMEBUFFER_COMPLETE){
            GLLog.loge("fbo创建异常");
        }
        else{
            GLLog.loge("fbo创建成功");
        }
        GLES32.glBindFramebuffer(GLES32.GL_FRAMEBUFFER, 0);
        //创建屏幕vao
        float rect[] = {
                //pos
                -1.0f, -1.0f, 0.0f,
                1.0f, -1.0f, 0.0f,
                1.0f, 1.0f, 0.0f,
                -1.0f, 1.0f, 0.0f,
                //uv
                0.0f, 0.0f,
                1.0f, 0.0f,
                1.0f, 1.0f,
                0.0f, 1.0f,
        };
        int index[] = {
                0, 1, 2,
                2, 3, 0,
        };
        mScreenVAO = new int[1];
        GLES32.glGenVertexArrays(1, mScreenVAO, 0);
        GLES32.glBindVertexArray(mScreenVAO[0]);
        int vbo[] = new int[1];
        GLES32.glGenBuffers(1, vbo, 0);
        GLES32.glBindBuffer(GLES32.GL_ARRAY_BUFFER, vbo[0]);
        FloatBuffer fb = GLBufferTools.getFloatBuffer(rect);
        GLES32.glBufferData(GLES32.GL_ARRAY_BUFFER, SizeOf.S_FLOAT_SIZE * rect.length, GLBufferTools.getFloatBuffer(rect), GLES32.GL_STATIC_DRAW);
        GLES32.glVertexAttribPointer(0x001, 3, GLES32.GL_FLOAT, false, SizeOf.S_FLOAT_SIZE * 3, 0);
        GLES32.glEnableVertexAttribArray(0x001);
        GLES32.glVertexAttribPointer(0x002, 2, GLES32.GL_FLOAT, false, SizeOf.S_FLOAT_SIZE * 2, 12 * SizeOf.S_FLOAT_SIZE);
        GLES32.glEnableVertexAttribArray(0x002);
        GLES32.glBindBuffer(GLES32.GL_ARRAY_BUFFER, 0);
        int ebo[] = new int[1];
        GLES32.glGenBuffers(1, ebo, 0);
        GLES32.glBindBuffer(GLES32.GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
        GLES32.glBufferData(GLES32.GL_ELEMENT_ARRAY_BUFFER, SizeOf.S_INT_SIZE * 6, GLBufferTools.getIntBuffer(index), GLES32.GL_STATIC_DRAW);
        GLES32.glBindVertexArray(0);
        GLES32.glBindBuffer(GLES32.GL_ELEMENT_ARRAY_BUFFER, 0);
        //shader
        mScreenShader = new Shader("fbo_vs.glsl", "fbo_fs.glsl");
        GLES32.glUseProgram(mScreenShader.mShaderProgram);
        GLES32.glUniform1i(GLES32.glGetUniformLocation(mScreenShader.mShaderProgram, "tex0"), 0);
        GLES32.glUseProgram(0);
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void render(float exTime) {
        super.render(exTime);
        GLES32.glUseProgram(mScreenShader.mShaderProgram);
        GLES32.glActiveTexture(GLES32.GL_TEXTURE0);
        GLES32.glBindTexture(GLES32.GL_TEXTURE_2D, mColorBuffer[0]);
        GLES32.glBindVertexArray(mScreenVAO[0]);
        GLES32.glDrawElements(GLES32.GL_TRIANGLES, 6, GLES32.GL_UNSIGNED_INT, 0);
        GLES32.glBindVertexArray(0);
        GLES32.glActiveTexture(GLES32.GL_TEXTURE0);
        GLES32.glBindTexture(GLES32.GL_TEXTURE_2D, 0);
        GLES32.glUseProgram(0);
    }

    @Override
    public void update(float exTime) {
        super.update(exTime);
    }
}
